﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using Newtonsoft.Json;
using ProjectN.Core.Instance.Data;

namespace ProjectN.Core.Element
{
    [TypeConverter(typeof(ExpandableObjectConverter))]
    [JsonObject]
    public abstract class Element : DataSpreader, IElement
    {
        public class DrawEventArgs(Graphics graphics, Color? color) : EventArgs
        {
            public Graphics Graphics { get; init; } = graphics;
            public Color? Color { get; init; } = color;
        };

        public class ClickEventArgs(Point pos) : EventArgs
        {
            public Point Position { get; init; } = pos;
        }

        public class LoadEventArgs(InstanceData InstanceData) : EventArgs
        {
            public InstanceData InstanceData { get; init; } = InstanceData;
        }

        public delegate void DrawEventHandler(object sender, DrawEventArgs e);
        public delegate void ClickEventHandler(object sender, ClickEventArgs e);
        public delegate void LoadEventHandler(object sender, LoadEventArgs e);

        public event DrawEventHandler? Draw;
        public event ClickEventHandler? Click;
        public event LoadEventHandler? Load;

        [JsonIgnore]
        [Browsable(false)]
        abstract public ElementType Type { get; }

        [JsonIgnore]
        [Browsable(false)]
        abstract public IEnumerable<IElement> Subelements { get; }

        public void OnClick(Point pos)
        {
            this.Click?.Invoke(this, new ClickEventArgs(pos));
        }

        public void OnDraw(Graphics graph, Color? color)
        {
            this.Draw?.Invoke(this, new DrawEventArgs(graph, color));
        }

        public void OnLoad(InstanceData InstanceData)
        {
            this.Load?.Invoke(this, new LoadEventArgs(InstanceData));
        }
    }

    public abstract class BasicElement : Element
    {
        protected readonly static IElement[] NoElement = [];
        public override ElementType Type { get { return ElementType.Basic; } }
        public override IEnumerable<IElement> Subelements { get { return NoElement; } }
    }

    public abstract class AdvancedElement : Element
    {
        public override ElementType Type { get { return ElementType.Advanced; } }
    }

    public abstract class MixedElement : Element
    {
        public override ElementType Type { get { return ElementType.Basic | ElementType.Advanced; } }
    }
}
